"""A simple agent implementation.

myAgent class inherits from BaseAgent and implement all three
abstract methods: setup(), step() and reset().
"""
import json
import os
# path = os.getcwd()#获取当前路径
import random
import pickle
import pandas as pd

from core.agent.base_agent import BaseAgent
from core.utils.map import Map
# from myAI.faction_ai import FactionAI
# from myAI.faction_ai_round_1 import FactionAI
# from myAI.faction_ai_round_2 import FactionAI
# from myAI.faction_ai_round_3 import FactionAI
# from myAI.faction_ai_round_4 import FactionAI
from myAI.faction_ai_round_5 import FactionAI
from myAI.perceive_situation import Situation

################# 同步 ########################
# from myAI.synchronize.raeAgenda import Agenda

################# 异步 ########################
# from myAI.asynchronous.raeAgenda import Agenda
from myAI.asynchronous.paralize_raeAgenda import Agenda

import threading
from multiprocessing import Queue, Process, Lock

from myAI.hexmap.handle_map import *
import copy
import time
import gc

class myAgent(BaseAgent):
    def __init__(self):
        self.scenario = None
        self.map_id = None
        self.color = None
        self.priority = None
        self.observation = None
        self.last_observation = None
        self.map = None
        self.my_map = None
        self.damage_matrix = None
        self.scenario_info = None
        self.max_step = None  # 想定的最大步数，分队：1800，群队：3000
        # 用于保存RAE对象
        self.agenda = None
        #用于保存上层AI对象
        self.factionAI = None
        # 初始化态势信息
        self.situations = None  # 用于将态势给rae和factionAI使用
        # self.situ = None        # 用于保存子线程不断更新的态势对象
        self.is_puppet = None
        # 运行模式
        self.runMode = None
        self.thread_rM = None
        self.thread_factionAI = None
        self.enemy_threat_process = None
        self.input_queue = None
        self.output_queue = None
        self.input_queue_lock = None
        self.output_queue_lock = None

    def setup(self, scenario: int, color: int):
        self.scenario = scenario
        self.get_map_id(scenario)
        self.get_scenario_info(scenario)
        self.color = color
        if scenario in [2010131194, 2010141294, 2010211129, 2010431153, 2010441253]:
            self.max_step = 1800
        else:
            self.max_step = 2880
        self.priority = {
            ActionType.Occupy: self.gen_occupy,
            ActionType.Shoot: self.gen_shoot,
            ActionType.GuideShoot: self.gen_guide_shoot,
            ActionType.JMPlan: self.gen_jm_plan,
            ActionType.GetOn: self.gen_get_on,
            ActionType.GetOff: self.gen_get_off,
            ActionType.ChangeState: self.gen_change_state,
            ActionType.RemoveKeep: self.gen_remove_keep,
            ActionType.Move: self.gen_move,
            ActionType.StopMove: self.gen_stop_move,
        }  # choose action by priority
        self.observation = None
        self.last_observation = self.scenario_info[-1]  # 保存上一步状态，便于和当前状态比较
        self.map = Map(scenario)  # use 'Map' class as a tool
        self.my_map = {}  # load_local_data()
        self.damage_matrix = {}  # 用于快速计算的期望损伤矩阵，load_local_data()
        self.load_local_data_1st()
        self.limit_map_range()
        self.load_local_data_2nd()
        # 创建agenda对象,用于保存维护各个堆栈的公共变量
        self.agenda = Agenda()
        # 创建上层AI对象
        # self.factionAI = FactionAI(color, scenario, self.scenario_info)
        self.factionAI = FactionAI(self)
        self.situations = Situation(self)
        # self.situ = Situation(self)
        self.input_queue = Queue(1)
        self.output_queue = Queue(1)
        self.input_queue_lock = Lock()
        self.output_queue_lock = Lock()
        self.is_puppet = []
        self.runMode = 1  # 0:同步模式，1：异步模式

    def reset(self):
        # begin0 = time.time()
        # print(f'reset begin')
        # 终止态势子进程
        if self.enemy_threat_process.is_alive():
            self.enemy_threat_process.terminate()
            print(f'terminate enemy_threat_process')
        self.enemy_threat_process = None

        # 终止我方算子子线程
        self.agenda.terminate_Allthread()
        # 结束agenda子线程
        self.thread_rM = None
        # 结束factionAI子线程
        self.thread_factionAI = None

        # 留出线程自己退出的时间
        time.sleep(0.2)

        # 将其他相关变量重置
        if self.agenda:
            self.agenda.agenda_reset()
            self.agenda = None

        self.scenario = None
        self.map_id = None
        self.color = None
        self.priority = None
        self.observation = None
        self.last_observation = None
        self.map = None
        self.my_map = None
        self.damage_matrix = None
        self.scenario_info = None
        self.max_step = None
        self.factionAI = None
        self.situations = None
        self.is_puppet = None
        self.runMode = None
        self.input_queue = None
        self.output_queue = None
        self.input_queue_lock = None
        self.output_queue_lock = None
        # 垃圾回收
        gc.collect()
        # print(f'reset end cost time: {time.time() - begin0:.3f}s')


    def step(self, observation: dict):
        # 同步模式
        if self.runMode == 0:
            self.observation = observation  # save observation for later use
            # begin_situations = time.time()
            self.situations.update(self)  # 更新态势信息
            # print((f'1. situations time: {time.time() - begin_situations:.3f}s'))

            # begin_factionAI = time.time()
            self.factionAI.update(self)  # 上层AI根据态势信息为算子分配任务
            # print((f'2. factionAI time: {time.time() - begin_factionAI:.3f}s'))

            # 将上层AI生成的task传递给执行引擎
            self.agenda.tasks = self.factionAI.task
            # 每次循环进来情况各个任务堆栈的共享变量total_actions，清除上一step产生的actions，保证返回的是本次step产生的actions
            self.agenda.ipcArgs.total_actions = []

            # begin_RAE = time.time()
            # 该函数用于轮询各个任务堆栈，每次进来轮询启动，每个堆栈返回action后，暂停
            self.agenda.ipcArgs.total_actions = self.agenda.raeMult(self)
            # print((f'3. RAE time: {time.time() - begin_RAE:.3f}s  current step: {observation["time"]["cur_step"]}'))

            if self.agenda.ipcArgs.total_actions:
                show_color = 'BLUE' if self.color else 'RED'
                print(f'|- {show_color} actions at step: {observation["time"]["cur_step"]}', end='\n\t')
                print(self.agenda.ipcArgs.total_actions)

            self.last_observation = observation

            return self.agenda.ipcArgs.total_actions

        # 异步模式
        else:
            # begin0 = time.time()
            # self.agenda.ipcArgs.mutex_observation.acquire()
            self.observation = observation  # save observation for later use
            # self.agenda.ipcArgs.mutex_observation.release()

            # 最后3个step不再向队列里放入数据，保证主进程能够顺利退出
            if (self.observation["time"]["cur_step"] >= self.max_step-2) and (self.observation["time"]["cur_step"] <= self.max_step):
                self.input_queue_lock.acquire()
                if self.input_queue.full():
                    self.input_queue.get()
                self.input_queue_lock.release()

                self.output_queue_lock.acquire()
                if self.output_queue.full():
                    self.output_queue.get()
                self.output_queue_lock.release()
                return []

            self.situations.situ_observation = observation

            # 用于查看主进程中是否存在跳帧的现象
            # print(f'myAgent current step: {self.observation["time"]["cur_step"]}')

            # begin1 = time.time()
            # self.agenda.ipcArgs.mutex_basic_situ.acquire()
            self.situations.our_oprs, self.situations.basic_enemies = self.situations.partition_operators(self.observation)
            self.situations.get_dead_enemies(self.observation, self.last_observation)
            self.situations.update_enemy_bullets(self.observation['judge_info'])
            self.situations.update_artillery_threat(self.observation)  # 实时更新炮兵威胁
            # self.agenda.ipcArgs.mutex_basic_situ.release()
            # print(f'【1】update basic_situ time: {time.time() - begin1:.3f}s')

            # begin2 = time.time()
            # 如果输入队列已满，则将队列中旧的态势对象删除，放入最新的态势对象（基本）
            self.input_queue_lock.acquire()
            if self.input_queue.full():
                self.input_queue.get()
            self.input_queue.put(self.situations)
            self.input_queue_lock.release()
            # print(f'+++ agent put input_queue: {self.situations.situ_observation["time"]["cur_step"]}')
            # print(f'【2】put input_queue time: {time.time() - begin2:.3f}s')

            # 开启独立子进程，用于不断更新态势
            if not self.enemy_threat_process:
                self.enemy_threat_process = Process(target=self.create_situatitons_process,
                                                    args=(self.input_queue, self.output_queue),
                                                    name='enemy_threat_process')
                self.enemy_threat_process.start()
                print(f'enemy_threat_process begin:')


            # 如果输出队列已满，则将队列中更新后的态势对象取出,赋给myAgent的situations
            # begin3 = time.time()
            self.output_queue_lock.acquire()
            # print(f'【1】myagent output_situ.enemies: {len(self.situations.enemies)}')
            if self.output_queue.full():
                # self.agenda.ipcArgs.mutex_situation.acquire()
                output_situ = self.output_queue.get()
                # print(f'【2】myagent output_situ.enemies: {len(output_situ.enemies_copy)}')
                self.situations.enemies = output_situ.enemies_copy
                self.situations.enemy_threat = output_situ.enemy_threat_copy
                # self.agenda.ipcArgs.mutex_situation.release()
                # print(f'--- agent get output_queue: {self.situations.situ_observation["time"]["cur_step"]}')
            self.output_queue_lock.release()
            # print(f'【3】myagent output_situ.enemies: {len(self.situations.enemies)}')
            # print(f'【3】get output_queue time: {time.time() - begin3:.3f}s')
            # print(f"\t|- 车辆威胁：{np.max(self.situations.enemy_threat[0])}")
            # print(f"\t|- 步兵威胁：{np.max(self.situations.enemy_threat[1])}")
            # print(f"\t|- 直升机威胁：{np.max(self.situations.enemy_threat[2])}")
            # print(f"\t|- 小型飞行器威胁：{np.max(self.situations.enemy_threat[3])}")

            # begin4 = time.time()
            self.factionAI.update(self)  # 上层AI根据态势信息为算子分配任务
            # print(f'【4】factionAI.update time: {time.time() - begin4:.3f}s')

            # 开启独立线程，用于上层AI生成任务
            # 当该线程出错时，能够重新启动，增加鲁棒性
            # if not self.thread_factionAI:
            #     self.thread_factionAI = threading.Thread(target=self.factionAI.update, args=[self])
            #     # rM.setDaemon(True)
            #     self.thread_factionAI.start()
            #     print(f'thread_factionAI begin:')

            # 开启独立线程，用于并行执行各个任务堆栈，产生算子行动
            if not self.thread_rM:
                self.thread_rM = threading.Thread(target=self.agenda.raeMult, args=[self])
                # rM.setDaemon(True)
                self.thread_rM.start()
                print(f'thread_rM begin:')

            result_actions = []
            # 如果执行引擎产生了算子行动，则将行动输出到兵棋引擎
            if len(self.agenda.ipcArgs.total_actions) > 0:
                show_color = 'BLUE' if self.color else 'RED'
                print(f'{show_color} actions at step: {observation["time"]["cur_step"]}', end='\n\t')
                # begin5 = time.time()
                # self.agenda.ipcArgs.mutex_actions.acquire()
                result_actions = copy.deepcopy(self.agenda.ipcArgs.total_actions)
                # self.agenda.ipcArgs.total_actions.clear()
                self.agenda.ipcArgs.total_actions = []
                # self.agenda.ipcArgs.mutex_actions.release()
                # print(f'【5】output result_actions time: {time.time() - begin5:.3f}s')
                print(result_actions)

            self.last_observation = observation

            # print(f'【6】total time: {time.time() - begin0:.3f}s')

            return result_actions

    def create_situatitons_process(self, input_queue, output_queue):
        # 创建进程中的situ态势对象
        situ = Situation(self)
        enemy_thread_dict = {}
        # 子进程内部用的锁
        mutex_basic_situ = threading.Lock()
        mutex_threat_situ = threading.Lock()
        situ.update(input_queue, output_queue, self.input_queue_lock, self.output_queue_lock, mutex_basic_situ, mutex_threat_situ, enemy_thread_dict, self)

    def get_bop_lastobservation(self, obj_id):
        """
        Get bop in my last_observation based on its id.
        """
        for bop in self.last_observation['operators']:
            if obj_id == bop['obj_id']:
                return bop
        for bop in self.last_observation['passengers']:
            if obj_id == bop['obj_id']:
                return bop
        return None

    def get_map_id(self, scenario: int):
        # data = pd.read_excel('/wgengine/land_war/core/Data/scenario.xlsx')
        file_path = os.path.join(os.getcwd(), 'core/Data/scenario.xlsx')
        data = pd.read_excel(file_path)
        self.map_id = data[data['scenarioID'] == self.scenario].iat[0, 1]

    def get_scenario_info(self, scenario: int):
        SCENARIO_INFO_PATH = os.path.join(os.path.dirname(__file__), f'scenario_{scenario}.json')
        with open(SCENARIO_INFO_PATH, encoding='utf8') as f:
            self.scenario_info = json.load(f)
            # 将读入的想定中key转为整型，与observation一致
            for key, value in self.scenario_info.items():
                self.scenario_info[int(key)] = self.scenario_info.pop(key)
                for opr in value['operators']:
                    for k in list(opr['remain_bullet_nums'].keys()):
                        opr['remain_bullet_nums'][int(k)] = opr['remain_bullet_nums'].pop(k)
                    for k in list(opr['observe_distance'].keys()):
                        opr['observe_distance'][int(k)] = opr['observe_distance'].pop(k)
                for opr in value['passengers']:
                    for k in list(opr['remain_bullet_nums'].keys()):
                        opr['remain_bullet_nums'][int(k)] = opr['remain_bullet_nums'].pop(k)
                    for k in list(opr['observe_distance'].keys()):
                        opr['observe_distance'][int(k)] = opr['observe_distance'].pop(k)

    def get_bop(self, obj_id):
        """ 2020-4-20
        Get bop in my observation based on its id.
        """
        for bop in self.observation['operators']:
            if obj_id == bop['obj_id']:
                return bop
        for bop in self.observation['passengers']:
            if obj_id == bop['obj_id']:
                return bop
        return None

    def get_enemy(self, obj_id):
        for enemy_info in self.situations.enemies:
            if enemy_info['obj_id'] == obj_id:
                return enemy_info['operator']
        return None

    def get_enemy_info(self, obj_id):
        for enemy_info in self.situations.enemies:
            if enemy_info['obj_id'] == obj_id:
                return enemy_info
        return None

    def get_city(self, city_loc):
        """ 2020-4-22
        通过夺控点位置，找出夺控点对象（本函数应该放在myAgent类的get_bop函数一起，建议后期移植）
        """
        for city in self.observation['cities']:
            if city['coord'] == city_loc:
                return city
        return None

    def get_map_size(self):
        """ 2020-4-26
        获取当前想定的行数和列数，行数（列数） = 最大行（最大列） + 1
        获取当前想定实际使用的地图范围
        """
        map_size = {
            'row': self.my_map['row_lim'][1] - self.my_map['row_lim'][0] + 1,
            'col': self.my_map['col_lim'][1] - self.my_map['col_lim'][0] + 1,
            'row_lim': self.my_map['row_lim'],
            'col_lim': self.my_map['col_lim']
        }
        return map_size

    def get_our_oprs(self):
        """ 2020-7-15 该函数比situation.our_oprs更实时
        获得我方所有的算子，包括车上算子
        """
        our_oprs = []
        if self.observation['operators']:
            for opr in self.observation['operators']:
                if opr['color'] == self.color and opr['lose_control'] == 0:  # 失去控制的算子不算是有效算子
                    our_oprs.append(opr)
        if self.observation['passengers']:
            for opr in self.observation['passengers']:  # 敌方的车上算子是看不到的
                if opr['color'] == self.color:
                    our_oprs.append(opr)
        return our_oprs

    def gen_occupy(self, obj_id, candidate):
        """Generate occupy action."""
        return {
            'obj_id': obj_id,
            'type': ActionType.Occupy,
        }

    def gen_shoot(self, obj_id, candidate):
        """Generate shoot action with the highest attack level."""
        best = max(candidate, key=lambda x: x['attack_level'])
        return {
            'obj_id': obj_id,
            'type': ActionType.Shoot,
            'target_obj_id': best['target_obj_id'],
            'weapon_id': best['weapon_id'],
        }

    def gen_guide_shoot(self, obj_id, candidate):
        """Generate guide shoot action with the highest attack level."""
        best = max(candidate, key=lambda x: x['attack_level'])
        return {
            'obj_id': obj_id,
            'type': ActionType.GuideShoot,
            'target_obj_id': best['target_obj_id'],
            'weapon_id': best['weapon_id'],
            'guided_obj_id': best['guided_obj_id'],
        }

    def gen_jm_plan(self, obj_id, candidate):
        """Generate jm plan action aimed at a random city."""
        weapon_id = random.choice(candidate)['weapon_id']
        jm_pos = random.choice([city['coord'] for city in self.observation['cities']])
        return {
            'obj_id': obj_id,
            'type': ActionType.JMPlan,
            'jm_pos': jm_pos,
            'weapon_id': weapon_id,
        }

    def gen_get_on(self, obj_id, candidate):
        """Generate get on action with some probability."""
        get_on_prob = 0.5
        if random.random() < get_on_prob:
            target_obj_id = random.choice(candidate)['target_obj_id']
            return {
                'obj_id': obj_id,
                'type': ActionType.GetOn,
                'target_obj_id': target_obj_id,
            }

    def gen_get_off(self, obj_id, candidate):
        """Generate get off action only if the bop is within some distance of a random city."""
        bop = self.get_bop(obj_id)
        destination = random.choice([city['coord'] for city in self.observation['cities']])
        if bop and self.map.get_distance(bop['cur_hex'], destination) <= 10:
            target_obj_id = random.choice(candidate)['target_obj_id']
            return {
                'obj_id': obj_id,
                'type': ActionType.GetOff,
                'target_obj_id': target_obj_id,
            }

    def gen_change_state(self, obj_id, candidate):
        """Generate change state action with some probability."""
        change_state_prob = 0.5
        if random.random() < change_state_prob:
            target_state = random.choice(candidate)['target_state']
            return {
                'obj_id': obj_id,
                'type': ActionType.ChangeState,
                'target_state': target_state,
            }

    def gen_remove_keep(self, obj_id, candidate):
        """Generate remove keep action with some probability."""
        remove_keep_prob = 0.5
        if random.random() < remove_keep_prob:
            return {
                'obj_id': obj_id,
                'type': ActionType.RemoveKeep,
            }

    def gen_move(self, obj_id, candidate):
        """Generate move action to a random city."""
        bop = self.get_bop(obj_id)
        destination = random.choice([city['coord'] for city in self.observation['cities']])
        if bop and bop['cur_hex'] != destination:
            move_type = self.get_move_type(bop)
            route = self.map.gen_move_route(bop['cur_hex'], destination, move_type)
            return {
                'obj_id': obj_id,
                'type': ActionType.Move,
                'move_path': route,
            }

    def get_move_type(self, bop):
        """Get appropriate move type for a bop."""
        bop_type = bop['type']
        if bop_type == BopType.Vehicle:
            if bop['move_state'] == MoveType.March:
                move_type = MoveType.March
            else:
                move_type = MoveType.Maneuver
        elif bop_type == BopType.Infantry:
            move_type = MoveType.Walk
        else:
            move_type = MoveType.Fly
        return move_type

    def gen_stop_move(self, obj_id, candidate):
        """Generate stop move action only if the bop is within some distance of a random city.

        High probability for the bop with passengers and low for others.
        """
        bop = self.get_bop(obj_id)
        destination = random.choice([city['coord'] for city in self.observation['cities']])
        if self.map.get_distance(bop['cur_hex'], destination) <= 10:
            stop_move_prob = 0.9 if bop['passenger_ids'] else 0.01
            if random.random() < stop_move_prob:
                return {
                    'obj_id': obj_id,
                    'type': ActionType.StopMove,
                }

    # def terminate_all_enemy_thread(self):
    #     for enemy_id in self.enemy_thread_dict.keys():
    #         self.agenda.terminate_thread(self.enemy_thread_dict[enemy_id])

    def load_local_data_1st(self):
        # file_path_0 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/map_row.pickle'
        file_path_0 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/map_row.pickle')
        with open(file_path_0, 'rb') as f:
            map_row = pickle.load(f)
        self.my_map['map_row'] = map_row

        # file_path_1 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/map_col.pickle'
        file_path_1 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/map_col.pickle')
        with open(file_path_1, 'rb') as f:
            map_col = pickle.load(f)
        self.my_map['map_col'] = map_col


        # file_path_8 = '/wgengine/land_war/myAI/data_in_use/damage_vehicle_matrix.pickle'
        file_path_8 = os.path.join(os.getcwd(),  'myAI/data_in_use/damage_vehicle_matrix.pickle')
        with open(file_path_8, 'rb') as f:
            damage_vehicle_matrix = pickle.load(f)
        self.damage_matrix[BopType.Vehicle] = damage_vehicle_matrix

        # file_path_9 = '/wgengine/land_war/myAI/data_in_use/damage_infantry_matrix.pickle'
        file_path_9 = os.path.join(os.getcwd(),  'myAI/data_in_use/damage_infantry_matrix.pickle')
        with open(file_path_9, 'rb') as f:
            damage_infantry_matrix = pickle.load(f)
        self.damage_matrix[BopType.Infantry] = damage_infantry_matrix

        # file_path_10 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/cost_data.pickle'
        file_path_10 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/cost_data.pickle')
        with open(file_path_10, 'rb') as f:
            cost_data = pickle.load(f)
        self.my_map['cost_data'] = cost_data

    def limit_map_range(self):
        """限制地图范围，只对与想定有关的局部地图进行计算，从而提高计算时效性"""
        scenatio_info = self.scenario_info[-1]
        # city_locs = [city['coord'] for city in scenatio_info['cities']]
        city_rows = [city['coord'] // 100 for city in scenatio_info['cities']]
        city_cols = [city['coord'] % 100 for city in scenatio_info['cities']]
        min_city_row, max_city_row = min(city_rows), max(city_rows)
        min_city_col, max_city_col = min(city_cols), max(city_cols)
        opr_rows = [opr['cur_hex'] // 100 for opr in scenatio_info['operators']]
        opr_cols = [opr['cur_hex'] % 100 for opr in scenatio_info['operators']]
        min_opr_row, max_opr_row = min(opr_rows), max(opr_rows)
        min_opr_col, max_opr_col = min(opr_cols), max(opr_cols)
        min_map_row, max_map_row = 0, self.my_map['map_row'] - 1
        min_map_col, max_map_col = 0, self.my_map['map_col'] - 1
        row_lim = (max(min(min_city_row - 25, min_opr_row), min_map_row),
                   min(max(max_city_row + 25, max_opr_row), max_map_row))
        col_lim = (max(min(min_city_col - 25, min_opr_col), min_map_col),
                   min(max(max_city_col + 25, max_opr_col), max_map_col))
        self.my_map['row_lim'], self.my_map['col_lim'] = row_lim, col_lim

    def load_local_data_2nd(self):
        all_patial_hexes_ind = []
        for row in range(self.my_map['row_lim'][0], self.my_map['row_lim'][1]+1):
            for col in range(self.my_map['col_lim'][0], self.my_map['col_lim'][1]+1):
                all_patial_hexes_ind.append(row * self.my_map['map_col'] + col)
        aph_ind = np.array(all_patial_hexes_ind)

        # file_path_2 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/see_matrix.pickle'
        file_path_2 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/see_matrix.pickle')
        with open(file_path_2, 'rb') as f:
            see_matrix = pickle.load(f)
        self.my_map['see_matrix'] = see_matrix[:, aph_ind.reshape(-1, 1), aph_ind.reshape(1, -1)]

        # file_path_3 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/dist_matrix.pickle'
        file_path_3 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/dist_matrix.pickle')
        with open(file_path_3, 'rb') as f:
            dist_matrix = pickle.load(f)
        self.my_map['dist_matrix'] = dist_matrix[aph_ind.reshape(-1, 1), aph_ind.reshape(1, -1)]

        # file_path_4 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/cost_matrix.pickle'
        file_path_4 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/cost_matrix.pickle')
        with open(file_path_4, 'rb') as f:
            cost_matrix = pickle.load(f)
        self.my_map['cost_matrix'] = cost_matrix[:, aph_ind.reshape(-1, 1), aph_ind.reshape(1, -1)]

        # file_path_5 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/elev_vec.pickle'
        file_path_5 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/elev_vec.pickle')
        with open(file_path_5, 'rb') as f:
            elev_vec = pickle.load(f)
        self.my_map['elev_vec'] = elev_vec[aph_ind]

        # file_path_6 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/elev_diff_matrix.pickle'
        file_path_6 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/elev_diff_matrix.pickle')
        with open(file_path_6, 'rb') as f:
            elev_diff_matrix = pickle.load(f)
        self.my_map['elev_diff_matrix'] = elev_diff_matrix[aph_ind.reshape(-1, 1), aph_ind.reshape(1, -1)]

        # file_path_7 = '/wgengine/land_war/myAI/data_in_use/map_' + str(self.map_id) + '/terrain_vec.pickle'
        file_path_7 = os.path.join(os.getcwd(),  'myAI/data_in_use/map_' + str(self.map_id) + '/terrain_vec.pickle')
        with open(file_path_7, 'rb') as f:
            terrain_vec = pickle.load(f)
        self.my_map['terrain_vec'] = terrain_vec[aph_ind]
